package com.sc.nft.admin.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.admin.request.*;
import com.sc.nft.admin.vo.BatchApprovalVO;
import com.sc.nft.annotation.RedissonLock;
import com.sc.nft.annotation.SysMemberLogin;
import com.sc.nft.dao.SandWithdrawRecordDao;
import com.sc.nft.dao.StaticDataDao;
import com.sc.nft.dao.UserInfoDao;
import com.sc.nft.dao.UserWalletDao;
import com.sc.nft.dto.HnaWithdrawDto;
import com.sc.nft.entity.Order;
import com.sc.nft.entity.SandWithdrawRecord;
import com.sc.nft.entity.StaticData;
import com.sc.nft.entity.dto.OperateUserWalletBatchAmountDTO;
import com.sc.nft.entity.dto.OperateUserWalletBatchDTO;
import com.sc.nft.entity.dto.SaveWithdrawRecordCauseDTO;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.SendSMSEnum;
import com.sc.nft.enums.WalletChannelEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.helper.LlPayHelper;
import com.sc.nft.service.*;
import com.sc.nft.service.impl.OperateUserWalletBatchFactory;
import com.sc.nft.sup.PageRequest;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/admin/wallet")
@Api(tags = "用户钱包")
public class UserWalletAdminController {
    private final DepositWithdrawalRecordService depositWithdrawalRecordService;
    private final StaticDataService staticDataService;
    private final CheckParameterService checkParameterService;
    private final UserWalletService userWalletService;
    private final OperateUserWalletBatchFactory operateUserWalletBatch;
    private final RedissonLock redissonLock;
    private final LlPayHelper llPayHelper;
    private final SandWithdrawRecordDao sandWithdrawRecordDao;
    private final SandWithdrawRecordDao withdrawRecordDao;
    private final UserHnaExtService userHnaExtService;


    @PostMapping(value = "/userWalletList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "用户钱包", notes = "用户钱包", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<UserWalletListVO> userWalletList(@Valid @RequestBody UserWalletListRequest request) {
        Page<UserWalletListVO> page = userWalletService.userWalletList(request.getUserTel(), request.getPageNo(), request.getPageSize());
        return PageResult.success(page);
    }





    @PostMapping(value = "/getRechargeRecord", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "充值记录", notes = "充值记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<RechargeRecordVO> getRechargeRecord(@Valid @RequestBody RechargeRecordRequest request) {
        Page<RechargeRecordVO> page = depositWithdrawalRecordService.getRechargeRecord(
                request.getStartTime(), request.getEndTime(), request.getOrderNo(),
                request.getPayStatus(), request.getUserTel(), request.getPageNo(), request.getPageSize());
        return PageResult.success(page);
    }

    @PostMapping(value = "/getWithdrawRecord", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "提现记录", notes = "提现记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<WithdrawRecordVO> getWithdrawRecord(@Valid @RequestBody WithdrawRecordRequest request) {
        Page<WithdrawRecordVO> page = withdrawRecordDao.getWithdrawRecord(request.getChannel(), request.getStartTime(), request.getEndTime(),
                request.getOrderNo(), request.getStatus(), request.getConfirmStatus(), request.getUserTel(),
                request.toMp());
        return PageResult.success(page);
    }

    @PostMapping(value = "/saveWithdrawRecordCause", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "修改提现原因", notes = "修改提现原因", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result saveWithdrawRecordCause(@Valid @RequestBody SaveWithdrawRecordCauseDTO request) {
        depositWithdrawalRecordService.saveWithdrawRecordCause(request);
        return Result.success();
    }

    @PostMapping(value = "/getNoAuditRechargeRecord", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取未审核的提现记录", notes = "获取未审核的提现记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<NoAuditRechargeRecordVO> getNoAuditRechargeRecord(@Valid @RequestBody PageRequest pageRequest) {
        Page<NoAuditRechargeRecordVO> page = depositWithdrawalRecordService.getNoAuditRechargeRecord(pageRequest.getPageNo(), pageRequest.getPageSize());
        return PageResult.success(page);
    }

    @PostMapping(value = "/getNoAuditRechargeRecordById", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "根据id获取未审核提现详情", notes = "根据id获取未审核提现详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<NoAuditRechargeRecordByIdVO> getNoAuditRechargeRecordById(@Valid @RequestBody IdRequest request) {
        NoAuditRechargeRecordByIdVO noRefundRechargeRecordByIdVO = depositWithdrawalRecordService.getNoAuditRechargeRecordById(request.getId());
        return Result.success(noRefundRechargeRecordByIdVO);
    }

    @PostMapping(value = "/getNoRefundRechargeRecord", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取未退费的提现记录", notes = "获取未退费的提现记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<NoRefundRechargeRecordVO> getNoRefundRechargeRecord(@Valid @RequestBody PageRequest pageRequest) {
        Page<NoRefundRechargeRecordVO> page = depositWithdrawalRecordService.getNoRefundRechargeRecord(pageRequest.getPageNo(), pageRequest.getPageSize());
        return PageResult.success(page);
    }

    @PostMapping(value = "/getNoRefundRechargeRecordById", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "根据id获取未退费的提现详情", notes = "根据id获取未退费的提现详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<NoRefundRechargeRecordByIdVO> getNoRefundRechargeRecordById(@Valid @RequestBody IdRequest request) {
        NoRefundRechargeRecordByIdVO noRefundRechargeRecordByIdVO = depositWithdrawalRecordService.getNoRefundRechargeRecordById(request.getId());
        return Result.success(noRefundRechargeRecordByIdVO);
    }

    @PostMapping(value = "/approval", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "审批", notes = "审批", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result approval(HttpServletRequest httpServletRequest, @Valid @RequestBody ApprovalWithdrawRequest request) {
        SandWithdrawRecord withdrawRecord = sandWithdrawRecordDao.getById(request.getId());
        if(ObjectUtil.isNull(withdrawRecord)){
            return Result.fail("未找到提现记录");
        }
        if(withdrawRecord.getConfirmStatus()){
            return Result.fail("该记录已经确认过了");
        }
        if (WalletChannelEnum.LL.equals(withdrawRecord.getChannel())) {
            llPayHelper.withdrawConfirm(withdrawRecord,request.getPassStatus(),request.getRemark());
        } else if(WalletChannelEnum.HNA.equals(withdrawRecord.getChannel())){
            HnaWithdrawDto dto = new HnaWithdrawDto();
            dto.setTranAmount(withdrawRecord.getAmount().toString());
            dto.setFeeAmount(withdrawRecord.getFeeAmount().toString());
            dto.setBindCardAgrNo(withdrawRecord.getRelatedCardNo());
            dto.setMerUserIp(ServletUtil.getClientIP(httpServletRequest));
            userHnaExtService.doWithdraw(withdrawRecord, request.getPassStatus(), dto, request.getRemark());
        }

        return Result.success();
    }



    @PostMapping(value = "/batchApproval", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "批量审批", notes = "批量审批", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<BatchApprovalVO> batchApproval(HttpServletRequest httpServletRequest, @Valid @RequestBody ApprovalBatchWithdrawRequest request) {
        int success = 0;
        int fail = 0;
        for (Long id : request.getIds()) {
            try {
                SandWithdrawRecord withdrawRecord = sandWithdrawRecordDao.getById(id);
                if (WalletChannelEnum.LL.equals(withdrawRecord.getChannel())) {
                    llPayHelper.withdrawConfirm(withdrawRecord,request.getPassStatus(),request.getRemark());
                } else if(WalletChannelEnum.HNA.equals(withdrawRecord.getChannel())){
                    HnaWithdrawDto dto = new HnaWithdrawDto();
                    dto.setTranAmount(withdrawRecord.getAmount().toString());
                    dto.setFeeAmount(withdrawRecord.getFeeAmount().toString());
                    dto.setBindCardAgrNo(withdrawRecord.getRelatedCardNo());
                    dto.setMerUserIp(ServletUtil.getClientIP(httpServletRequest));
                    userHnaExtService.doWithdraw(withdrawRecord, request.getPassStatus(), dto, request.getRemark());
                }
                success++;
            } catch (Exception e) {
                fail++;
            }
        }
        BatchApprovalVO batchApprovalVO = new BatchApprovalVO();
        batchApprovalVO.setSuccessCount(success);
        batchApprovalVO.setFailCount(fail);
        return Result.success(batchApprovalVO);
    }



    @PostMapping(value = "/operateUserWallet", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "操作用户钱包余额", notes = "操作用户钱包余额", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result operateUserWallet(@Valid @RequestBody OperateUserWalletRequest request) {
        String noticePhone = staticDataService.getByType("notice_phone").getValue();
        checkParameterService.CheckVerificationcode(noticePhone,
                request.getSmsId(),
                request.getCodes(),
                SendSMSEnum.OPERATING_BALANCE.getCode());

        userWalletService.operateUserWallet(request.getUserTel(), request.getIsType(), request.getAmount(), request.getRemark(), request.getUserBalanceType());
        return Result.success();
    }

    @PostMapping(value = "/operateUserWalletBatch", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "批量操作用户余额", notes = "批量操作用户余额", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result operateUserWalletBatch(@Valid @RequestBody OperateUserWalletBatchDTO operateUserWalletBatchDTO) {
        String lockName = StrUtil.format("operateUserWalletBatch");
        boolean lock = redissonLock.isLock(lockName);
        if (lock) {
            throw new GlobalRunTimeException("当前功能正在被操作,请稍后再试");
        }
        redissonLock.lock(lockName);
        try {
          // 验证用户手机
          String noticePhone = staticDataService.getByType("notice_phone").getValue();
          checkParameterService.CheckVerificationcode(noticePhone,
                  operateUserWalletBatchDTO.getSmsId(),
                  operateUserWalletBatchDTO.getCodes(),
                  SendSMSEnum.OPERATING_BALANCE.getCode());
          // 根据路由处理对应的方法
          operateUserWalletBatch.getUserWalletAdminBatch(operateUserWalletBatchDTO.getUserBalanceType()).operateUserWalletBatch(operateUserWalletBatchDTO);
      }catch (Exception e){
            log.error("批量操作用户余额异常",e);
            throw new GlobalRunTimeException("批量操作用户余额异常");
      }finally {
            redissonLock.unlock(lockName);
        }
        return Result.success();
    }

    @PostMapping(value = "/operateUserWalletBatchList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "批量操作用户余额功能查询列表", notes = "批量操作用户余额功能查询列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<List<OperateUserWalletBatchListVO>> operateUserWalletBatchList(@Valid @RequestBody List<OperateUserWalletBatchAmountDTO> userMoney) {
        List<OperateUserWalletBatchListVO> info=new ArrayList<>();
        userMoney.forEach(operateUserWalletBatchAmountDTO -> {
            List<OperateUserWalletBatchAmountDTO>data=new ArrayList<>();
            data.add(operateUserWalletBatchAmountDTO);
            List<OperateUserWalletBatchListVO> operateUserWalletBatchLists = userWalletService.operateUserWalletBatchList(data);
            if (CollUtil.isEmpty(operateUserWalletBatchLists)) {
                return;
            }
            OperateUserWalletBatchListVO operateUserWalletBatchListVO = operateUserWalletBatchLists.get(0);
            operateUserWalletBatchListVO.setAmount(operateUserWalletBatchListVO.getAmount());
            operateUserWalletBatchListVO.setBalance(operateUserWalletBatchListVO.getBalance());
            operateUserWalletBatchListVO.setPayBalance(operateUserWalletBatchListVO.getPayBalance());
            operateUserWalletBatchListVO.setOperationAmount(operateUserWalletBatchAmountDTO.getAmount());
            operateUserWalletBatchListVO.setNickName(operateUserWalletBatchListVO.getNickName());
            operateUserWalletBatchListVO.setUserTel(operateUserWalletBatchListVO.getUserTel());
            info.add(operateUserWalletBatchListVO);
        });
        return Result.success(info);
    }




}
